package org.bookshare.validator.report;

import java.util.HashMap;
import java.util.Map;

import org.benetech.collections.Tree;
import org.bookshare.document.beans.HasXML;
import org.jdom.Document;
import org.jdom.Element;

/**
 * Generates a Tree object representing the major structural elements of each
 * xml document in the package.
 * @author Reuben Firmin
 */
public final class XMLStructureReportGenerator implements ReportGenerator {

	/**
	 * Default constructor.
	 */
	public XMLStructureReportGenerator() {
		// empty
	}

    /**
     * {@inheritDoc}
     */
    public String getModelKey() {
        return "headings";
    }

    /**
     * {@inheritDoc}
     */
    public void addToReport(final ValidationMetadata report) {
        final Map<String, Tree> documentTreeMap = new HashMap<String, Tree>();
        final Document doc = ((HasXML)report.getDocumentSet()).getXMLDocument();
        final Element root = doc.getRootElement();
        final Tree<Element, String, String> base = new Tree<Element, String, String>();
        base.setContent(root);
        recurseAndBuildTree(base, root);
        documentTreeMap.put(doc.getBaseURI(), base);
        report.getModelMap().put(getModelKey(), documentTreeMap);
    }

    /**
     * Recursive method which looks at the children of the given node
     * to discover whether they are interesting enough to add to the tree
     * and parse in turn. Depth first parsing.
     * @param branch The branch of the tree that children should be added to.
     * @param node The element of the document that  is relative to the tree's
     * branch.
     */
    public void recurseAndBuildTree(final Tree<Element, String, String> branch,
            final Element node)
    {
        for (Object object : node.getChildren()) {
            if (object instanceof Element) {
            	final Element element = (Element) object;
                if (element.getName().startsWith("level")
                        || element.getName().equals("book")
                        || element.getName().equals("frontmatter")
                        || element.getName().equals("bodymatter")
                        || element.getName().equals("rearmatter")) {
                    final Tree<Element, String, String> newBranch = new Tree<Element, String, String>();
                    newBranch.setContent(element);
                    branch.addChild(newBranch);
                    recurseAndBuildTree(newBranch, element);
                } else if (element.getName().equals("pagenum")) {
                    branch.addMetaContent("pagenum", element.getText());
                } else {
                    // dig into the node anyway
                    recurseAndBuildTree(branch, element);
                }
            }
        }
    }



}


